import 'dart:convert' as convert;

import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:ichinesereader/exam/dto/assessment.response.dart';
import 'package:ichinesereader/exam/dto/assessment_question_record.body.dart';
import 'package:ichinesereader/exam/widgets/BGSinglePlayer.dart';
import 'package:ichinesereader/models/assessment/questionResult.dart';
import 'package:ichinesereader/service/assessment.dart';
import 'package:ichinesereader/utils/log.dart';
import 'package:just_audio/just_audio.dart';

import 'BGAPExamQuestionIndexPage.dart';
import 'BGCountdownContoller.dart';

class BGAPExamController extends GetxController {
  final AssessmentServiceProvider _service = AssessmentServiceProvider();
  AssessmentResult? assessmentResult;
  QuestionResult? questionResult;
  List<UiPartIndex> partIndexList = [];
  List<UiQuestionStep> questionStepList = [];
  Rx<int> currentQuestionStepIndex = 0.obs;
  Rx<QuestionContent?> currentQuestionStepTopic = QuestionContent().obs;
  Rx<QuestionItem> currentQuestionStepBody = QuestionItem().obs;

  UiQuestionStep? currentQuestionStep;
  UiPartIndex? currentUiPartIndex;
  UiSectionIndex? currentUiSectionIndex;
  UiQuestionIndex? currentUiQuestionIndex;
  Rx<bool> isPrevPageEnable = false.obs;
  Rx<bool> isNextPageEnable = false.obs;

  Rx<bool> isTest = false.obs;
  Rx<bool> isTestCompleted = false.obs;
  Rx<bool> isHideTimer = false.obs;
  final count = 0.obs;
  RxInt countSeconds = 0.obs;
  bool isTestReading = true;
  bool isPrepareTime = false;
  final BGCountdownController timerVC = BGCountdownController();
  RxInt speakActionNum = 0.obs;

  void _resetWidgetStatusAction() {
    BGSinglePlayer().stop();
  }

  void prevPage() {
    if (currentQuestionStepIndex.value == 0) return;
    _resetWidgetStatusAction();
    currentQuestionStepIndex.value--;
    _reportRecord(currentQuestionStepIndex.value + 1);
    _resetPageActionButtonState();
    _resetPageInfo();
  }

  void _resetPageActionButtonState() {
    isPrevPageEnable.value = currentQuestionStepIndex.value > 0;
    isNextPageEnable.value = currentQuestionStepIndex.value < questionStepList.length - 1;
  }

  void nextPage() {
    if (currentQuestionStepIndex.value >= questionStepList.length - 1) return;
    _resetWidgetStatusAction();
    currentQuestionStepIndex.value++;
    _reportRecord(currentQuestionStepIndex.value - 1);
    _resetPageActionButtonState();
    _resetPageInfo();
  }

  void reportCurrentPageRecord() {
    _resetWidgetStatusAction();
    _reportRecord(currentQuestionStepIndex.value);
  }

  void gotoPage(int questionStepIndex) {
    _resetWidgetStatusAction();
    _reportRecord(currentQuestionStepIndex.value);
    currentQuestionStepIndex.value = questionStepIndex;
    _resetPageActionButtonState();
    _resetPageInfo();
  }

  void submitAction() {
    _resetWidgetStatusAction();
    _submitReportRecord(currentQuestionStepIndex.value);
  }

  List verifyCompleteAllQuestion() {
    AssessmentResult? result = assessmentResult;
    var partDataList = result!.list;
    List<String> questionNumList = [];
    //Part
    for (var pIndex = 0; pIndex < partDataList!.length; pIndex++) {
      var partData = partDataList[pIndex];
      var sectionDataList = partData.questions;
      //Section
      for (var sIndex = 0; sIndex < sectionDataList!.length; sIndex++) {
        var sectionData = sectionDataList[sIndex];
        var questionDataList = sectionData.question;
        //Question
        for (var qIndex = 0; qIndex < questionDataList!.length; qIndex++) {
          QuestionItem questionData = questionDataList[qIndex];
          String questionTitleNum = '';
          if (partDataList.length > 1) questionTitleNum = (pIndex + 1).toString() + '-';
          questionTitleNum += ' ' + (sIndex + 1).toString();
          if (questionDataList.length > 1) questionTitleNum += '.' + (qIndex + 1).toString();

          if (questionData.answer == null ||
              questionData.answer!.isEmpty ||
              questionData.answer![0].endsWith('.m4a') ||
              questionData.answer![0].startsWith('blob:http')) {
            questionNumList.add(questionTitleNum);
          } else {
            if (questionData.answerCount != null && questionData.answerCount! > 1 && questionData.answer!.length < questionData.answerCount!) {
              questionNumList.add(questionTitleNum);
            }
          }
        }
      }
    }
    return questionNumList;
  }

  Future<void> _reportRecord(int answerPageIndex) async {
    if (isTestCompleted.value) return;
    EasyLoading.show();
    try {
      _service.postQuestionRecord(QuestionRecordBody(
          assessmentId: Get.arguments['id'],
          questionGroupId: assessmentResult?.questionGroupId ?? Get.arguments['questionGroupId'],
          userName: Get.arguments['userName'],
          progressStatus: "{\"pageIndex\":${currentQuestionStepIndex.value}}",
          record: _buildQuestionRecordList(answerPageIndex)));
    } catch (e) {
      Log.debug(e);
    } finally {
      EasyLoading.dismiss();
    }
  }

  Future<void> _submitReportRecord(int answerPageIndex) async {
    EasyLoading.show();
    try {
      _service.postSubmitReportRecord(QuestionRecordBody(
          assessmentId: Get.arguments['id'],
          questionGroupId: assessmentResult?.questionGroupId ?? Get.arguments['questionGroupId'],
          userName: Get.arguments['userName'],
          progressStatus: "{\"pageIndex\":${currentQuestionStepIndex.value}}",
          record: _buildQuestionRecordList(answerPageIndex)));
    } catch (e) {
      Log.debug(e);
    } finally {
      Future.delayed(const Duration(milliseconds: 500), () {
        EasyLoading.dismiss();
        if (isTest.value) {
          isTestCompleted.value = true;
        } else {
          Get.back();
        }
      });
    }
  }

  List<Map> _buildQuestionRecordList(int answerPageIndex) {
    List<Map> questionRecordList = [];
    AssessmentResult? result = assessmentResult;
    var partDataList = result!.list;
    //Part
    for (var pIndex = 0; pIndex < partDataList!.length; pIndex++) {
      var partData = partDataList[pIndex];
      var sectionDataList = partData.questions;

      //Section
      for (var sIndex = 0; sIndex < sectionDataList!.length; sIndex++) {
        var sectionData = sectionDataList[sIndex];
        var questionDataList = sectionData.question;
        //Question
        for (var qIndex = 0; qIndex < questionDataList!.length; qIndex++) {
          QuestionItem questionData = questionDataList[qIndex];

          if (!(questionData.answer == null ||
              questionData.answer!.isEmpty ||
              questionData.answer![0].endsWith('.m4a') ||
              questionData.answer![0].startsWith('blob:http'))) {
            questionRecordList.add(QuestionSingleStep(answer: questionData.answer, number: questionData.number, questionId: sectionData.id).toJson());
          }
        }
      }
    }

    return questionRecordList;
  }

  void _resetPageInfo() {
    var oldQuestionStep = currentQuestionStep;
    currentQuestionStep = questionStepList[currentQuestionStepIndex.value];
    //reset index
    void _resetUiPartUiSectionUiQuestionIndex() {
      //reset index
      currentUiSectionIndex = null;
      currentUiQuestionIndex = null;

      if ((currentQuestionStep?.partIndex ?? -1) > -1) {
        currentUiPartIndex = partIndexList[currentQuestionStep?.partIndex ?? 0];
      }
      if ((currentQuestionStep?.sectionIndex ?? -1) > -1) {
        currentUiSectionIndex = partIndexList[currentQuestionStep?.partIndex ?? 0].sectionIndexList![currentQuestionStep?.sectionIndex ?? 0];
      }
      if ((currentQuestionStep?.questionIndex ?? -1) > -1) {
        currentUiQuestionIndex = partIndexList[currentQuestionStep?.partIndex ?? 0]
            .sectionIndexList![currentQuestionStep?.sectionIndex ?? 0]
            .questionIndexList![currentQuestionStep?.questionIndex ?? 0];
      }
    }

    _resetUiPartUiSectionUiQuestionIndex();
    int partIndex = currentQuestionStep?.partIndex ?? 0;
    QuestionPart? questionPart = assessmentResult?.list![partIndex];
    if (currentQuestionStep?.stepType == UiQuestionStep.STEPTYPE_PARTPROMPT) {
      countSeconds.value = 0;
      isTestReading = true;
      Future.delayed(const Duration(milliseconds: 100), () {
        countSeconds.value = 10;
        _timerStart();
      });
    }
    if (currentQuestionStep?.stepType == UiQuestionStep.STEPTYPE_QUESTION) {
      int sectionIndex = currentQuestionStep?.sectionIndex ?? 0;
      QuestionSection? questionSection = questionPart?.questions?[sectionIndex];
      int questionIndex = currentQuestionStep?.questionIndex ?? 0;
      QuestionItem? questionItem = questionSection?.question?[questionIndex];

      QuestionContent? questionHead;
      bool isQuestionLevelTopic = true;
      //如果 section 級別的問題，那麽走 section 獲取題目信息
      if (questionSection?.content != null && StringUtil.isNotBankValue(questionSection?.content?.show)) {
        isQuestionLevelTopic = false;
        QuestionContent? tempQuestionHead = questionSection?.content;
        questionHead = QuestionContent(
            show: tempQuestionHead?.show,
            text: tempQuestionHead?.text,
            audio: tempQuestionHead?.audio,
            image: tempQuestionHead?.image,
            json: '%content%');
      }
      //否則 就是 question級別的問題
      else {
        isQuestionLevelTopic = true;
        questionHead = questionItem?.head;
        questionItem?.head?.json = '%hidden%';
      }
      if (isTest.value && questionItem?.head != null) questionItem?.head?.json = questionItem.head?.json ?? '' + '%isTest%';
      //如果是 QuestionLevelTopic 每次都刷新， 或者  新老 sectionIndex 不一样的时候刷新
      if (isQuestionLevelTopic ||
          currentQuestionStep?.partIndex != oldQuestionStep?.partIndex ||
          currentQuestionStep?.sectionIndex != oldQuestionStep?.sectionIndex ||
          currentQuestionStepTopic.value?.show == null) {
        if (isTest.value && questionHead != null) questionHead.json = questionHead.json! + '%isTest%';
        currentQuestionStepTopic.value = questionHead;
      }
      currentQuestionStepBody.value = questionItem!;
      if (isTest.value) {
        String? audioUrl = currentQuestionStepTopic.value?.audio;
        int? questionNum = currentQuestionStepBody.value.number;
        int? prepareTime = currentQuestionStepBody.value.prepareTime;
        if (questionPart?.partType != null && questionPart?.partType == 'READING') {
          if (isTestReading) {
            isTestReading = false;
            countSeconds.value = 0;
            Future.delayed(const Duration(milliseconds: 100), () {
              countSeconds.value = 3600;
              _timerStart();
            });
          }
        } else {
          countSeconds.value = 0;
          Future.delayed(const Duration(milliseconds: 100), () {
            if (prepareTime == null) {
              countSeconds.value = currentQuestionStepBody.value.limitTime ?? 10;
            } else {
              countSeconds.value = prepareTime;
            }
          });
        }

        if (audioUrl == null) {
          if (questionPart?.partType != null && questionPart?.partType != 'READING') _timerStart();
        } else {
          if (questionNum != null) {
            String? itemHeadAudioUrl = currentQuestionStepBody.value.head?.audio;
            if (questionNum == 1) {
              BGSinglePlayer().playDirect(audioUrl);
            } else {
              if (currentQuestionStepBody.value.prepareTime == null) {
                if (itemHeadAudioUrl != null) {
                  BGSinglePlayer().playDirect(itemHeadAudioUrl);
                } else {
                  _timerStart();
                  if (questionPart?.partType != null && questionPart?.partType == 'SPEAKING') {
                    Future.delayed(const Duration(milliseconds: 200), () {
                      speakActionNum.value = 1;
                    });
                  }
                }
              } else {
                _timerStart();
                if (isPrepareTime) {
                  isPrepareTime = false;
                  if (questionPart?.partType != null && questionPart?.partType == 'SPEAKING') {
                    Future.delayed(const Duration(milliseconds: 200), () {
                      speakActionNum.value = 1;
                    });
                  }
                }
              }
            }

            BGSinglePlayer().audioPlayer.playerStateStream.listen((playerState) {
              if (playerState.playing == false && playerState.processingState == ProcessingState.completed) {
                if (currentQuestionStepBody.value.prepareTime == null) {
                  if (questionNum == 1 && itemHeadAudioUrl != null && itemHeadAudioUrl != audioUrl) {
                    BGSinglePlayer().playDirect(itemHeadAudioUrl);
                    audioUrl = itemHeadAudioUrl;
                  } else {
                    _timerStart();
                    if (questionPart?.partType != null && questionPart?.partType == 'SPEAKING') {
                      Future.delayed(const Duration(milliseconds: 200), () {
                        speakActionNum.value = 1;
                      });
                    }
                  }
                } else {
                  _timerStart();
                  if (isPrepareTime) {
                    isPrepareTime = false;
                    if (questionPart?.partType != null && questionPart?.partType == 'SPEAKING') {
                      Future.delayed(const Duration(milliseconds: 200), () {
                        speakActionNum.value = 1;
                      });
                    }
                  }
                }
              }
            });
          }
        }
      }
    }
  }

  void dealPrepareTimeSpeakingAction() {
    countSeconds.value = 0;
    Future.delayed(const Duration(milliseconds: 100), () {
      countSeconds.value = currentQuestionStepBody.value.limitTime ?? 10;
    });
    String? itemHeadAudioUrl = currentQuestionStepBody.value.head?.audio;
    if (itemHeadAudioUrl != null) {
      isPrepareTime = true;
      BGSinglePlayer().playDirect(itemHeadAudioUrl);
    } else {
      _timerStart();
      int partIndex = currentQuestionStep?.partIndex ?? 0;
      QuestionPart? questionPart = assessmentResult?.list![partIndex];
      if (questionPart?.partType != null && questionPart?.partType == 'SPEAKING') {
        Future.delayed(const Duration(milliseconds: 200), () {
          speakActionNum.value = 1;
        });
      }
    }
  }

  void _timerStart() {
    Future.delayed(const Duration(milliseconds: 200), () {
      timerVC.start();
    });
  }

  @override
  void onInit() {
    super.onInit();
  }

  @override
  void onReady() {
    super.onReady();
  }

  @override
  void onClose() {}

  void increment() => count.value++;

  void loadData(String assessmentId) {
    EasyLoading.show();

    getAssessment(assessmentId);

    Future.delayed(const Duration(milliseconds: 2000), () {
      EasyLoading.dismiss();
    });
  }

  Future<void> getAssessment(String assessmentId) async {
    try {
      var result = await _service.getAssessment(assessmentId);
      assessmentResult = result;
      isTest.value = assessmentResult?.mode == 'Test';
      _resetWidgetStatusAction();
      _buildExamUiPartIndex(result);
      _buildQuestionStepList(result);
      _buildInitPageInfo(result);
    } catch (e) {
      Log.debug(e);
    } finally {}
  }

  void _buildInitPageInfo(AssessmentResult? result) {
    currentQuestionStepIndex.value = 0;
    currentQuestionStep = questionStepList[currentQuestionStepIndex.value];
    if (result?.progressStatus != null) {
      Map<String, dynamic> progress = convert.jsonDecode(result?.progressStatus ?? "");
      if (progress.isNotEmpty) {
        currentQuestionStepIndex.value = progress['pageIndex'];
        currentQuestionStep = questionStepList[currentQuestionStepIndex.value];
      }
    }
    _resetPageActionButtonState();
    _resetPageInfo();
  }

  void _buildQuestionStepList(AssessmentResult? result) {
    questionStepList.clear();
    var partDataList = result!.list;
    //Part
    int questionStepIndex = -1;
    for (var pIndex = 0; pIndex < partDataList!.length; pIndex++) {
      var partData = partDataList[pIndex];
      UiPartIndex partIndex = UiPartIndex('$pIndex', 'Part ${pIndex + 1}');

      questionStepIndex++;
      questionStepList.add(UiQuestionStep(questionStepIndex, partIndex.name, 'partprompt', partIndex: pIndex));

      var sectionDataList = partData.questions;
      //Section
      for (var sIndex = 0; sIndex < sectionDataList!.length; sIndex++) {
        var sectionData = sectionDataList[sIndex];
        UiSectionIndex sectionIndex = UiSectionIndex('$sIndex', 'Q ${sIndex + 1}');
        //有下边的 content 带表 是section 级别的问题， 无content 带表是 question级别的问题

        var questionDataList = sectionData.question;
        //Question
        for (var qIndex = 0; qIndex < questionDataList!.length; qIndex++) {
          UiQuestionIndex questionIndex =
              UiQuestionIndex('$qIndex', '${sIndex + 1}.${qIndex + 1}', partIndex: pIndex, sectionIndex: sIndex, questionIndex: qIndex);

          questionStepIndex++;
          questionStepList.add(UiQuestionStep(questionStepIndex, '${partIndex.name}-${sectionIndex.name}-${questionIndex.name}', 'question',
              partIndex: pIndex, sectionIndex: sIndex, questionIndex: qIndex));
        }
      }
    }
  }

  void _buildExamUiPartIndex(AssessmentResult? result) {
    partIndexList.clear();
    var partDataList = result!.list;
    int questionStepIndex = -1;
    for (var pIndex = 0; pIndex < partDataList!.length; pIndex++) {
      var partData = partDataList[pIndex];
      UiPartIndex partIndex = UiPartIndex('$pIndex', 'Part ${pIndex + 1}');
      questionStepIndex++;
      partIndex.sectionIndexList = [];
      var sectionDataList = partData.questions;
      for (var sIndex = 0; sIndex < sectionDataList!.length; sIndex++) {
        var sectionData = sectionDataList[sIndex];
        UiSectionIndex sectionIndex = UiSectionIndex('$sIndex', 'Q ${sIndex + 1}');
        sectionIndex.questionIndexList = [];

        var questionDataList = sectionData.question;
        for (var qIndex = 0; qIndex < questionDataList!.length; qIndex++) {
          questionStepIndex++;
          var itemName = '${sIndex + 1}.';
          if (questionDataList.length > 1) itemName += '${qIndex + 1}';
          UiQuestionIndex questionIndex = UiQuestionIndex('$qIndex', itemName,
              partIndex: pIndex, sectionIndex: sIndex, questionIndex: qIndex, questionStepIndex: questionStepIndex);
          sectionIndex.questionIndexList!.add(questionIndex);
        }
        partIndex.sectionIndexList!.add(sectionIndex);
      }
      partIndexList.add(partIndex);
    }
  }
}

class StringUtil {
  static bool isBankValue(String? str) {
    if (str == null) return true;
    if (str.trim().isEmpty) return true;
    return false;
  }

  static bool isNotBankValue(String? str) {
    return !isBankValue(str);
  }
}
